package com.ssy.lingxi.search.serviceImpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.constant.tree.Node;
import com.ssy.lingxi.common.constant.tree.TreeUtils;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.search.api.model.response.*;
import com.ssy.lingxi.search.common.tree.CategoryNode;
import com.ssy.lingxi.search.entity.Commodity;
import com.ssy.lingxi.search.entity.SimpleCustomerAttribute;
import com.ssy.lingxi.search.entity.SimpleCustomerAttributeValue;
import com.ssy.lingxi.search.repository.CommodityRepository;
import com.ssy.lingxi.search.service.ICommodityService;
import com.ssy.lingxi.search.service.IStoreService;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 店铺实现类
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/6/22
 */
@Service
public class StoreServiceImpl implements IStoreService {

    @Resource
    private ICommodityService commodityService;

    @Resource
    private CommodityRepository commodityRepository;

    @Resource
    private RestHighLevelClient restHighLevelClient;

    @Resource
    private IRedisStringUtils redisStringUtils;

    /**
     * 查询商品分类树
     * @param storeId 店铺id
     * @return
     */
    @Override
    public List<Node> getCategoryTree(Long shopId, Long storeId) {
        String esField = "customerCategory.fullId.keyword";
        String redisKey = Constants.REDIS_KEY_CUSTOMER_CATEGORY;
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if(storeId != null && storeId >0){
            queryBuilder.must(QueryBuilders.matchQuery("storeId", storeId));
        }

        // 按商城环境
        if(shopId != null && shopId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.shopId", shopId));
        }

        //构建查询条件
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().trackTotalHits(true);
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);

        //分组
        TermsAggregationBuilder aggregationCategoryId = AggregationBuilders.terms("group_categoryId").field(esField).size(1200000);
        searchSourceBuilder.aggregation(aggregationCategoryId);
        search.source(searchSourceBuilder);
        try{
            CategoryNode categoryNode = new CategoryNode();
            //搜索
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms brandTerms = aggregations.get("group_categoryId");
                List<? extends Terms.Bucket> brandBuckets = brandTerms.getBuckets();
                if(brandBuckets != null){
                    brandBuckets.forEach(bucket -> {
                        //将品类进行组装
                        String fullId = String.valueOf(bucket.getKey());
                        if(fullId.contains(Constants.SPLIT_STR_FULL_ID)){
                            String[] split = fullId.split(Constants.TRANSFER_STR + Constants.SPLIT_STR_FULL_ID);
                            if(split.length > 0){
                                for(int i = 0; i < split.length; i++){
                                    if(i == 0){
                                        //一级品类
                                        Set<Long> rootList = categoryNode.getRootList() == null ? new HashSet<>() : categoryNode.getRootList();
                                        rootList.add(Long.valueOf(split[i]));
                                        categoryNode.setRootList(rootList);
                                    }
                                    //所有品类
                                    Set<Long> sourceList = categoryNode.getSourceList() == null ? new HashSet<>() : categoryNode.getSourceList();
                                    sourceList.add(Long.valueOf(split[i]));
                                    categoryNode.setSourceList(sourceList);
                                }
                            }
                        }else{
                            //商品挂在一级品类下
                            Set<Long> rootList = categoryNode.getRootList() == null ? new HashSet<>() : categoryNode.getRootList();
                            rootList.add(Long.valueOf(fullId));
                            categoryNode.setRootList(rootList);
                            //所有品类
                            Set<Long> sourceList = categoryNode.getSourceList() == null ? new HashSet<>() : categoryNode.getSourceList();
                            sourceList.add(Long.valueOf(fullId));
                            categoryNode.setSourceList(sourceList);
                        }
                    });
                }
            }
            Map<String, String> categoryMap = redisStringUtils.hGetAll(redisKey, Constants.REDIS_PRODUCT_INDEX);
            Set<Long> rootCategoryIdList = categoryNode.getRootList();
            Set<Long> sourceCategoryIdList = categoryNode.getSourceList();
            //组装树结构
            if(rootCategoryIdList != null && !rootCategoryIdList.isEmpty()){
                List<Node> rootList = TreeUtils.getNodeList(rootCategoryIdList, categoryMap);
                List<Node> sourceList = TreeUtils.getNodeList(sourceCategoryIdList, categoryMap);
                return TreeUtils.buildTree(sourceList, rootList);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return new ArrayList<>();
    }

    /**
     * 查询商品品类树和对应的品牌
     * @param storeId 店铺id
     * @return
     */
    @Override
    public List<CategoryTreeBrandResponse> getCategoryTreeAndBrand(Long shopId, Long storeId) {
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if(storeId != null && storeId >0){
            queryBuilder.must(QueryBuilders.matchQuery("storeId", storeId));
        }

        // 按商城环境
        if(shopId != null && shopId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.shopId", shopId));
        }

        //构建查询条件
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);

        //分组
        TermsAggregationBuilder aggregationCategory = AggregationBuilders.terms("group_categoryId").field("customerCategory.fullId.keyword").size(1200000)
                .subAggregation(AggregationBuilders.terms("group_brandId").field("brand.id.keyword"));
        searchSourceBuilder.aggregation(aggregationCategory);
        search.source(searchSourceBuilder);

        try{
            CategoryNode categoryNode = new CategoryNode();
            Map<Long, Set<BrandResponse>> categoryBrandMap = new HashMap<>();
            //搜索
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms categoryIdTerms = aggregations.get("group_categoryId");
                List<? extends Terms.Bucket> categoryIdBuckets = categoryIdTerms.getBuckets();
                if(categoryIdBuckets != null){
                    Map<String, String> brandMap = redisStringUtils.hGetAll(Constants.REDIS_KEY_BRAND, Constants.REDIS_PRODUCT_INDEX);

                    categoryIdBuckets.forEach(categoryIdBucket -> {
                        //将品类进行组装
                        String fullId = String.valueOf(categoryIdBucket.getKey());
                        Long categoryId = null;
                        if(fullId.contains(Constants.SPLIT_STR_FULL_ID)){
                            String[] split = fullId.split(Constants.TRANSFER_STR + Constants.SPLIT_STR_FULL_ID);
                            if(split.length > 0){
                                for(int i = 0; i < split.length; i++){
                                    if(i == 0){
                                        //一级品类
                                        Set<Long> rootList = categoryNode.getRootList() == null ? new HashSet<>() : categoryNode.getRootList();
                                        rootList.add(Long.valueOf(split[i]));
                                        categoryNode.setRootList(rootList);
                                    }
                                    //所有品类
                                    Set<Long> sourceList = categoryNode.getSourceList() == null ? new HashSet<>() : categoryNode.getSourceList();
                                    sourceList.add(Long.valueOf(split[i]));
                                    categoryNode.setSourceList(sourceList);

                                }

                                categoryId = Long.valueOf(split[split.length - 1]);
                            }
                        }else{
                            //商品挂在一级品类下
                            Set<Long> rootList = categoryNode.getRootList() == null ? new HashSet<>() : categoryNode.getRootList();
                            rootList.add(Long.valueOf(fullId));
                            categoryNode.setRootList(rootList);
                            //所有品类
                            Set<Long> sourceList = categoryNode.getSourceList() == null ? new HashSet<>() : categoryNode.getSourceList();
                            sourceList.add(Long.valueOf(fullId));
                            categoryNode.setSourceList(sourceList);

                            categoryId = Long.valueOf(fullId);
                        }

                        //获取品牌信息
                        Set<BrandResponse> brandList = new HashSet<>();
                        Terms brandIdTerms = categoryIdBucket.getAggregations().get("group_brandId");
                        List<? extends Terms.Bucket> brandIdBuckets = brandIdTerms.getBuckets();
                        if(brandIdBuckets != null){
                            brandIdBuckets.forEach(brandIdBucket -> {
                                String brandId = String.valueOf(brandIdBucket.getKey());
                                String brand = brandMap.get(brandId);
                                JSONObject jsonObject = JSONUtil.parseObj(brand);
                                String brandName = jsonObject.getStr("name");
                                String brandLogoUrl = jsonObject.getStr("logoUrl");

                                BrandResponse brandResponse = new BrandResponse();
                                brandResponse.setId(Long.valueOf(brandId));
                                brandResponse.setName(brandName);
                                brandResponse.setLogoUrl(brandLogoUrl);
                                brandList.add(brandResponse);
                            });
                        }

                        categoryBrandMap.put(categoryId, brandList);
                    });
                }
            }

            Map<String, String> categoryMap = redisStringUtils.hGetAll(Constants.REDIS_KEY_CUSTOMER_CATEGORY, Constants.REDIS_PRODUCT_INDEX);
            Set<Long> rootCategoryIdList = categoryNode.getRootList();
            Set<Long> sourceCategoryIdList = categoryNode.getSourceList();
            //组装树结构
            if(rootCategoryIdList != null && !rootCategoryIdList.isEmpty()){
                List<Node> rootList = TreeUtils.getNodeList(rootCategoryIdList, categoryMap);
                List<Node> sourceList = TreeUtils.getNodeList(sourceCategoryIdList, categoryMap);
                List<Node> categoryTree = TreeUtils.buildTree(sourceList, rootList);

                return categoryTree.stream().map(node -> {
                    CategoryTreeBrandResponse categoryTreeBrandResponse = BeanUtil.copyProperties(node, CategoryTreeBrandResponse.class);
                    Long customerCategoryId = Long.parseLong(node.getId());
                    Set<BrandResponse> result = categoryBrandMap.get(customerCategoryId);
                    categoryTreeBrandResponse.setBrandList(result);
                    return categoryTreeBrandResponse;
                }).collect(Collectors.toList());
            }
            return new ArrayList<>();
        }catch (Exception e){
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    /**
     * 查询商品属性
     * @param storeId
     * @param categoryId
     * @return
     */
    @Override
    public List<AttributeResponse> getAttributeByCategoryId(Long shopId, Long storeId, Long categoryId) {
        HashMap<Long, AttributeResponse> attributeMap = new HashMap<>();
        List<Commodity> commodityList = new ArrayList<>();
        // 会员id
        if(storeId != null && storeId > 0){
            commodityList = commodityRepository.findByStoreIdAndCustomerCategoryIdAndCommodityShopListShopId(storeId, categoryId, shopId);
        }
        Map<String, String> attributeSortMap = redisStringUtils.hGetAll(Constants.REDIS_KEY_CUSTOMER_CATEGORY_ATTRIBUTE_SORT + categoryId, Constants.REDIS_PRODUCT_INDEX);
        commodityList.forEach(commodity -> commodity.getCommodityAttributeList().forEach(commodityAttribute -> {
            SimpleCustomerAttribute customerAttribute = commodityAttribute.getCustomerAttribute();
            if(customerAttribute != null){
                Long attributeId = customerAttribute.getId();
                String attributeName = customerAttribute.getName();
                Boolean isSearch = customerAttribute.getIsSearch();
                if(isSearch){
                    List<SimpleCustomerAttributeValue> customerAttributeValueSet = commodityAttribute.getCustomerAttributeValueList();
                    customerAttributeValueSet.forEach(customerAttributeValue -> {
                        AttributeValueResponse attributeValueResponse = new AttributeValueResponse();
                        attributeValueResponse.setId(customerAttributeValue.getId());
                        attributeValueResponse.setValue(customerAttributeValue.getValue());

                        AttributeResponse attributeResponse = attributeMap.get(attributeId);
                        if(attributeResponse != null){
                            List<AttributeValueResponse> attributeValueList = attributeResponse.getAttributeValueList();
                            if(attributeValueList != null){
                                if(!attributeValueList.contains(attributeValueResponse)){
                                    attributeValueList.add(attributeValueResponse);
                                }
                            }else{
                                attributeValueList = new ArrayList<>();
                                attributeValueList.add(attributeValueResponse);
                            }
                        }else{
                            attributeResponse = new AttributeResponse();
                            attributeResponse.setId(attributeId);
                            attributeResponse.setName(attributeName);

                            List<AttributeValueResponse> attributeValueList = new ArrayList<>();
                            attributeValueList.add(attributeValueResponse);
                            attributeResponse.setAttributeValueList(attributeValueList);
                        }

                        String sort = attributeSortMap.get(String.valueOf(attributeId));
                        if (StringUtils.isNotBlank(sort)){
                            attributeResponse.setSort(Integer.valueOf(sort));
                        }else {
                            attributeResponse.setSort(0);
                        }

                        attributeMap.put(attributeId, attributeResponse);
                    });
                }
            }
        }));

        List<AttributeResponse> attributeResponses = new ArrayList<>(attributeMap.values());
        //属性排序
        attributeResponses = attributeResponses.stream().sorted(Comparator.comparingInt(AttributeResponse::getSort)).collect(Collectors.toList());

        return attributeResponses;
    }

    /**
     * 查询商品品牌
     * @return
     */
    @Override
    public List<BrandResponse> getBrand(Long shopId, Long storeId) {
        List<BrandResponse> brandList = new ArrayList<>();
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        // 拼接店铺搜索
        if(storeId != null && storeId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("storeId", storeId));
        }

        // 按商城环境
        if(shopId != null && shopId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.shopId", shopId));
        }

        //构建查询条件
        SearchRequest search = new SearchRequest(Constants.ES_COMMODITY_INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.size(0);
        searchSourceBuilder.query(queryBuilder);
        //分组
        TermsAggregationBuilder aggregationBrandId = AggregationBuilders.terms("group_brandId").field("brand.id").size(1200000)
                .subAggregation(AggregationBuilders.terms("group_brandName").field("brand.name.keyword").subAggregation(AggregationBuilders.terms("group_brandLogoUrl").field("brand.logoUrl.keyword")));
        searchSourceBuilder.aggregation(aggregationBrandId);
        search.source(searchSourceBuilder);
        //搜索
        try{
            SearchResponse searchResponse = restHighLevelClient.search(search, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if(aggregations != null){
                Terms brandTerms = aggregations.get("group_brandId");
                List<? extends Terms.Bucket> brandBuckets = brandTerms.getBuckets();
                if(brandBuckets != null){
                    brandBuckets.forEach(bucket -> {
                        Terms brandNameTerms = bucket.getAggregations().get("group_brandName");
                        List<? extends Terms.Bucket> brandNameBuckets = brandNameTerms.getBuckets();
                        if(brandNameBuckets != null){
                            brandNameBuckets.forEach(bucketName -> {
                                Terms brandLogoUrlTerms = bucketName.getAggregations().get("group_brandLogoUrl");
                                List<? extends Terms.Bucket> brandLogoUrlBuckets = brandLogoUrlTerms.getBuckets();
                                brandLogoUrlBuckets.forEach(bucketLogoUrl -> {
                                    BrandResponse brand = new BrandResponse();
                                    brand.setId(Long.valueOf(String.valueOf(bucket.getKey())));
                                    brand.setName(String.valueOf(bucketName.getKey()));
                                    brand.setLogoUrl(String.valueOf(bucketLogoUrl.getKey()));
                                    brandList.add(brand);
                                });
                            });
                        }
                    });
                }
            }
            return brandList;
        }catch (Exception e){
            return new ArrayList<>();
        }
    }

    /**
     * 查询归属地市
     * @param storeId
     * @return
     */
    @Override
    public List<ProvinceResponse> getArea(Long shopId, Long storeId) {
        // 查询条件
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();

        // 拼接店铺搜索
        if(storeId != null && storeId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("storeId", storeId));
        }

        // 按商城环境
        if(shopId != null && shopId > 0){
            queryBuilder.must(QueryBuilders.matchQuery("commodityShopList.shopId", shopId));
        }
        return commodityService.queryEsArea(queryBuilder);
    }
}